{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "9b2bc88e",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "import os\n",
    "import numpy as np\n",
    "from datetime import datetime\n",
    "from pandas import read_csv\n",
    "from sklearn.mixture import GaussianMixture\n",
    "from sklearn import preprocessing\n",
    "from sklearn.metrics import silhouette_score, calinski_harabasz_score, davies_bouldin_score\n",
    "import joblib\n",
    "\n",
    "# 定义输入和输出文件夹路径\n",
    "input_folder = \"/root/bt/code/data\"\n",
    "\n",
    "# 获取输入文件夹中所有以 P 开头且以 .csv 结尾的文件\n",
    "file_list = [f for f in os.listdir(input_folder) if f.startswith('P') and f.endswith('.csv')]\n",
    "all_filtered_dfs = []"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "5ee85a93",
   "metadata": {},
   "outputs": [],
   "source": [
    "def custom_parse(x):\n",
    "    return datetime.strptime(x, '%Y-%m-%d %H:%M:%S.%f')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "1e53a7a0",
   "metadata": {},
   "outputs": [],
   "source": [
    "def time_count(filtered_df):\n",
    "    result = (filtered_df.shape[0]-1)*10\n",
    "    result = round(result/(1000*60*60), 4)\n",
    "    return result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "3865cd55",
   "metadata": {},
   "outputs": [],
   "source": [
    "def df_pred(file_path):\n",
    "    # 修改为使用自定义解析函数读取 CSV 文件\n",
    "    df = read_csv(file_path, header=0, parse_dates=[0], date_parser=custom_parse)\n",
    "    # 提取数字部分（如 11585）\n",
    "    df['class'] = df['annotation'].str.extract(r'(\\d+)')\n",
    "    # 提取 MET 值部分（如 1.5）\n",
    "    df['MET'] = df['annotation'].str.extract(r'MET\\s(\\d+(\\.\\d+)?)')[0]\n",
    "    # 删除原始第四列（可选）\n",
    "    df.drop(columns=['annotation'], inplace=True)\n",
    "    # 将 class 和 MET 列转换为数值类型\n",
    "    df['class'] = pd.to_numeric(df['class'])\n",
    "    df['MET'] = pd.to_numeric(df['MET'])\n",
    "    # 直接将时间列转换为时间戳（毫秒）\n",
    "    df['timestamp_ms'] = df.iloc[:, 0].astype('int64') // 10**6\n",
    "    # 按照 timestamp_ms 从小到大排序\n",
    "    df.sort_values(by='timestamp_ms', inplace=True)\n",
    "    # 删除原始第四列（可选）\n",
    "    df.drop(columns=['timestamp_ms'], inplace=True)\n",
    "    return df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "d1fe62e5",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_9170/1329330421.py:3: FutureWarning: The argument 'date_parser' is deprecated and will be removed in a future version. Please use 'date_format' instead, or read your data in as 'object' dtype and then call 'to_datetime'.\n",
      "  df = read_csv(file_path, header=0, parse_dates=[0], date_parser=custom_parse)\n",
      "/tmp/ipykernel_9170/1329330421.py:3: DtypeWarning: Columns (4) have mixed types. Specify dtype option on import or set low_memory=False.\n",
      "  df = read_csv(file_path, header=0, parse_dates=[0], date_parser=custom_parse)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "          x         y        z\n",
      "0  0.421797  0.057012 -0.90087\n",
      "1  0.421797  0.041310 -0.90087\n",
      "2  0.421797  0.041310 -0.90087\n",
      "3  0.421797  0.057012 -0.90087\n",
      "4  0.421797  0.057012 -0.90087\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/tmp/ipykernel_9170/1329330421.py:3: FutureWarning: The argument 'date_parser' is deprecated and will be removed in a future version. Please use 'date_format' instead, or read your data in as 'object' dtype and then call 'to_datetime'.\n",
      "  df = read_csv(file_path, header=0, parse_dates=[0], date_parser=custom_parse)\n",
      "/tmp/ipykernel_9170/1329330421.py:3: DtypeWarning: Columns (4) have mixed types. Specify dtype option on import or set low_memory=False.\n",
      "  df = read_csv(file_path, header=0, parse_dates=[0], date_parser=custom_parse)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "          x         y         z\n",
      "0 -0.306289  0.207828 -0.916929\n",
      "1 -0.306289  0.207828 -0.933021\n",
      "2 -0.306289  0.207828 -0.916929\n",
      "3 -0.306289  0.192112 -0.933021\n",
      "4 -0.306289  0.207828 -0.916929\n",
      "6061\n"
     ]
    }
   ],
   "source": [
    "for file_name in file_list:\n",
    "    file_path = os.path.join(input_folder, file_name)\n",
    "    try:\n",
    "        df = df_pred(file_path)\n",
    "        # print(df.iloc[1])\n",
    "        df.iloc[:, 5] = pd.to_numeric(df.iloc[:, 5], errors='coerce')  # 数据类型转换\n",
    "        # 按照要求 MET<1.0 为睡眠，提取 MET<1.0 的数据\n",
    "        filtered_df = df[df.iloc[:, 5] < 1.0]\n",
    "        filtered_df = filtered_df.iloc[:, 1:4]\n",
    "        all_filtered_dfs.append(filtered_df)\n",
    "        print(filtered_df.head())\n",
    "\n",
    "    except Exception as e:\n",
    "        print(f\"Error processing {file_path}: {e}\")\n",
    "\n",
    "# 合并所有过滤后的数据\n",
    "combined_filtered_df = pd.concat(all_filtered_dfs)\n",
    "combined_filtered_df = combined_filtered_df[::1000]\n",
    "print(combined_filtered_df.shape[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "50342e61",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 数据标准化\n",
    "scaler = preprocessing.StandardScaler()\n",
    "scaled_data = scaler.fit_transform(combined_filtered_df)\n",
    "best_score = -1\n",
    "best_labels = None\n",
    "best_n_components = None\n",
    "best_gmm = None"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "2707cc5b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "总共分了 5 类，最优的 n_components 值为 5。\n",
      "轮廓系数: 0.4585926426860234\n",
      "Calinski - Harabasz 指数: 4701.125807160576\n",
      "Davies - Bouldin 指数: 0.824332802756334\n",
      "模型已保存为 best_gmm_model.joblib\n",
      "Scaler 已保存为 scaler.joblib\n"
     ]
    }
   ],
   "source": [
    "# 尝试不同的 n_components 值\n",
    "for n_components in range(2, 7):\n",
    "    gmm = GaussianMixture(n_components=n_components, random_state=42)\n",
    "    labels = gmm.fit_predict(scaled_data)\n",
    "    num_clusters = len(set(labels))\n",
    "\n",
    "    if 2 <= num_clusters <= 5:\n",
    "        if num_clusters >= 5:\n",
    "            score = silhouette_score(scaled_data, labels)\n",
    "            if score > best_score:\n",
    "                best_score = score\n",
    "                best_labels = labels\n",
    "                best_n_components = n_components\n",
    "                best_gmm = gmm\n",
    "\n",
    "if best_labels is not None:\n",
    "    # 统计分类的数量\n",
    "    num_clusters = len(set(best_labels))\n",
    "    print(f\"总共分了 {num_clusters} 类，最优的 n_components 值为 {best_n_components}。\")\n",
    "\n",
    "    # 评估模型效果\n",
    "    silhouette_avg = silhouette_score(scaled_data, best_labels)\n",
    "    ch_score = calinski_harabasz_score(scaled_data, best_labels)\n",
    "    db_score = davies_bouldin_score(scaled_data, best_labels)\n",
    "\n",
    "    print(f\"轮廓系数: {silhouette_avg}\")\n",
    "    print(f\"Calinski - Harabasz 指数: {ch_score}\")\n",
    "    print(f\"Davies - Bouldin 指数: {db_score}\")\n",
    "\n",
    "    # 保存模型\n",
    "    joblib.dump(best_gmm, 'best_gmm_model.joblib')\n",
    "    # 保存 scaler\n",
    "    joblib.dump(scaler, 'scaler.joblib')\n",
    "    print(\"模型已保存为 best_gmm_model.joblib\")\n",
    "    print(\"Scaler 已保存为 scaler.joblib\")\n",
    "\n",
    "    # 以下是加载模型进行预测的示例\n",
    "    loaded_model = joblib.load('best_gmm_model.joblib')\n",
    "    loaded_scaler = joblib.load('scaler.joblib')\n",
    "    new_predictions = loaded_model.predict(loaded_scaler.transform(combined_filtered_df))\n",
    "else:\n",
    "    print(\"未找到合适的 n_components 值使得分类数量在 2 至 6 类之间。\")\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
